package com.study.kt._02feature

fun main() {
    //testLet(FunBean())
    //testWith()
    //testRun(FunBean("slx", 12))
    //testApply()
    //testTakeIf()
    testAlso()
}

fun testAlso() {
}

fun testTakeIf() {
    val takeIf = "abc".takeIf {
        println(it)
        //最后一个行为返回值，如果返回true，则takeIf赋值为变量本身
        //如果返回false则takeIf返回null
        true
    }
    println(takeIf)
}

//apply函数和run函数使用一致，不同的是返回值：run函数返回lambda函数体最后一样，而apply函数返回对象本身
fun testApply() {
    val res = "abc".apply {
        println(length)
        println(indexOf('b'))
    }

    println(res)
}

/**
 * let函数可以做统一的判空操作，但是不能省略对象名称调用函数、方法
 * with函数可以省略对象名，但是没有统一判断空操作
 * run函数结合以上两者的优点,run函数函数体的最后一行为返回值
 */
fun testRun(f: FunBean?) {
    val res = f?.run {
        sayHello()
        sayHi()
        println(name)
        //返回end字符串
        "end"
    }

    println(res)
}

/**
 * with函数常用于一个对象调用多个方法省略对象名称
 * 常见场景是在RecyclerView中绑定Holder省略Item的对象名
 */
fun testWith() {
    var f = FunBean("fauks", 12)
    println("${f.name} == ${f.age}")

    //使用with函数简化上述代码
    with(f) {
        //使用属性、方法：可以直接省略对象名
        println("$name == $age")
        sayHello()
    }
}

//let函数
//let扩展函数的实际上是一个作用域函数，当你需要去定义一个变量在一个特定的作用域范围内，let函数的是一个不错的选择；let函数另一个作用就是可以避免写一些判断null的操作
//与let相似的还有also函数，不同的是返回值，let函数返回函数体最后一行，而also返回this，适用于链式调用的情景
fun testLet(f: FunBean?) {
    //常规操作,对f做非空判断
    f?.sayHi()
    f?.sayHello()

    //let函数可以做统一的判空操作，如果f不为空则做操作，可以使用it指代f对象
    f?.let {
        it.sayHello()
        it.sayHi()
    }
}


class FunBean {

    var name: String = ""
    var age: Int = 0

    constructor(name: String, age: Int) {
        this.name = name
        this.age = age
    }


    fun sayHello() {
        println("hello")
    }

    fun sayHi() {
        println("hi")
    }
}